package com.sojoys.artifact.factory.bytebuff;

import java.util.Arrays;


public class ArrayByteBuff extends IByteBuff {
	/** 增长量 */
	public static final int DEFAULT_ADD_CAPACITY = 64;
	/** 初始大小 */
	public static final int DEFAULT_CAPACITY = 256;
	/** 数据 */
	private byte[] data;
	/** 每次增加长度 */
	private int addCapacity = 0;
	/** 读索引 */
	private int readIndex = 0;
	/** 写索引 */
	private int writeIndex = 0;

	
	/**
	 * 注意：如果传入data数据时，initCapacity参数将失效并且把数据放入开始位置
	 * @param initCapacity 初始大小
	 * @param addCapacity	增长量
	 * @param data			数据
	 */
	private ArrayByteBuff(int initCapacity, int addCapacity, byte[] data) {
		if (data == null) {
			this.data = new byte[initCapacity];
		}else {
			this.data = data;
			this.writeIndex += (data.length-1);
		}
		this.addCapacity = addCapacity;
	}

	/**
	 * 默认配置构建
	 * @return
	 */
	public static ArrayByteBuff allocate() {
		return new ArrayByteBuff(DEFAULT_CAPACITY, DEFAULT_ADD_CAPACITY, null);
	}

	/**
	 * 指定初始大小构建
	 * @param initCapacity 初始大小
	 * @return
	 */
	public static ArrayByteBuff allocate(int initCapacity) {
		return new ArrayByteBuff(initCapacity, DEFAULT_ADD_CAPACITY, null);
	}

	/**
	 * 自定义大小、增长量 构建
	 * @param initCapacity 初始大小
	 * @param addCapacity	增长量
	 * @return
	 */
	public static ArrayByteBuff allocate(int initCapacity, int addCapacity) {
		return new ArrayByteBuff(initCapacity, addCapacity, null);
	}

	/**
	 * 通过已有数据构建
	 * @param data
	 * @return
	 */
	public static ArrayByteBuff wrap(byte[] data) {
		return new ArrayByteBuff(DEFAULT_CAPACITY, DEFAULT_ADD_CAPACITY, data);
	}

	/**
	 * 通过指定数据构建
	 * @param array 	数据
	 * @param offset	开始位置
	 * @param length	数据长度
	 * @return
	 */
	public static ArrayByteBuff wrap(byte[] array, int offset, int length) {
		byte[] data = new byte[length];
		System.arraycopy(array, offset, data, 0, length);
		return new ArrayByteBuff(DEFAULT_CAPACITY, DEFAULT_ADD_CAPACITY, data);
	}

	/**
	 * 检查长度
	 * @param l 需要的长度
	 */
	private void checkLength(int l) {
		int length = this.data.length;
		int spill = (writeIndex + l) - length;
		if (spill < addCapacity) {
			this.data = Arrays.copyOf(this.data, length + addCapacity);
		}else {
			this.data = Arrays.copyOf(this.data, length + l + (l % addCapacity));
		}
	}

	/**
	 * 重置读、写位置
	 * @return
	 */
	public IByteBuff reset() {
		this.readIndex = 0;
		this.writeIndex = 0;
		return this;
	}

	/**
	 * 数据大小
	 * @return
	 */
	public int size() {
		return this.data.length;
	}
	
//	public boolean available(){
//		if (this.readIndex >= this.data.length)
//			return false;
//		return true;
//	}
	
	public boolean isRead(){
		if (this.readIndex > this.writeIndex)
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "SK_ByteBuff [data=" + Arrays.toString(data) + ", addCapacity="
				+ addCapacity + ", readIndex=" + readIndex + ", writeIndex="
				+ writeIndex + "]";
	}

	protected void _writeByte(byte v) {
		checkLength(1);
		this.data[writeIndex++] = v;
	}

	protected void _writeBytes(byte[] v) {
		checkLength(v.length);
		System.arraycopy(v, 0, this.data, writeIndex, v.length);
		writeIndex += v.length;
	}
	
	protected byte _readByte() {
		if (this.isRead())
			return this.data[readIndex++];
		return 0;
	}

	protected byte[] _readBytes(int readLength) {
		if ((this.readIndex+readLength) > this.data.length)
			return new byte[]{};
		byte[] b = new byte[readLength];
		System.arraycopy(this.data, this.readIndex, b, 0, readLength);
		this.readIndex += readLength;
		return b;
	}

	/**
	 * 转换byte数据
	 * @return
	 */
	public byte[] toByte() {
		return Arrays.copyOfRange(data, 0, writeIndex);
	}
}
